using System.IO;
using Framework.Core.Recorder;
using Xunit;

namespace Framework.Tests.Core.Recorder.AcceptanceTests
{
    public class DefensiveProgrammingTest
    {
        public interface IGoodInterface
        {
            IGoodInterface Do();
            string Do(IGoodInterface goodInterface);
        }

        public class NotSerializable : IGoodInterface
        {
            public IGoodInterface Do()
            {
                return new NotSerializable();
            }

            public string Do(IGoodInterface goodInterface)
            {
                return "pouet";
            }
        }

        interface IToRecord
        {
            bool IsPouet(string toCompare);
        }

        class ToRecord : IToRecord
        {
            public bool IsPouet(string toCompare)
            {
                return toCompare == "pouet";
            }
        }

        [Fact]
        public void Should_fail_if_type_is_not_interface()
        {
            var ex = Assert.Throws<HardMockException>(() => new HardMock().BuildRecorderOver(new ToRecord()));

            Assert.Equal("type should be an interface", ex.Message);
        }

        [Fact]
        public void Should_fail_if_interface_is_not_public()
        {
            var ex = Assert.Throws<HardMockException>(() => new HardMock().BuildRecorderOver<IToRecord>(new ToRecord()));

            Assert.Equal("type should be public", ex.Message);
        }

        [Fact]
        public void Should_fail_if_type_can_be_hashed_for_return_value()
        {
            var recorder = new HardMock().BuildRecorderOver<IGoodInterface>(new NotSerializable());
            var ex = Assert.Throws<HardMockException>(() =>
                                                      {
                                                          Assert.NotNull(recorder.Do());
                                                          using (var stream = new MemoryStream())
                                                          {
                                                              recorder.Snapshot(stream);
                                                          }
                                                      });

            Assert.Equal("Type 'Framework.Tests.Core.Recorder.AcceptanceTests.DefensiveProgrammingTest+NotSerializable' in Assembly 'Framework.Tests, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' is not marked as serializable.", ex.Message);
        }

        [Fact]
        public void Should_fail_if_type_can_be_hashed_for_parameter_value()
        {
            var recorder = new HardMock().BuildRecorderOver<IGoodInterface>(new NotSerializable());
            var ex = Assert.Throws<HardMockException>(() => Assert.NotNull(recorder.Do(new NotSerializable())));

            Assert.Equal("Type 'Framework.Tests.Core.Recorder.AcceptanceTests.DefensiveProgrammingTest+NotSerializable' in Assembly 'Framework.Tests, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' is not marked as serializable.", ex.Message);
        }
    }
}
